{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "name": "Chapter 14",
      "provenance": [],
      "collapsed_sections": [],
      "include_colab_link": true
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "accelerator": "GPU"
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "view-in-github",
        "colab_type": "text"
      },
      "source": [
        "<a href=\"https://colab.research.google.com/github/jo-cho/advances_in_financial_machine_learning/blob/master/Chapter_14.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "WsBgyz5OKvew",
        "colab_type": "text"
      },
      "source": [
        "# Statistics of backtest"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "XHy5VzrEF4H4",
        "colab_type": "text"
      },
      "source": [
        "\n",
        "\n",
        "1. General characteristics - \n",
        "  - **Time range**: Time range specifies the start and end dates. The period used to\n",
        "test the strategy should be **sufficiently long to include a comprehensive number**\n",
        "of regimes (Bailey and Lopez de Prado [2012]).\n",
        "\n",
        "  - **Average AUM**: This is the average dollar value of the assets under management.\n",
        "For the purpose of computing this average, the dollar value of long and\n",
        "short positions is considered to be a positive real number.\n",
        "\n",
        "  - **Capacity**: A strategy’s capacity can be measured as the **highest AUM that delivers a target risk-adjusted performance**. A minimum AUM is needed to ensure proper bet sizing and risk diversification. Beyond that minimum AUM, performance will decay as AUM increases, due to higher transaction costs and lower turnover.\n",
        "\n",
        "  - **Leverage**: Leverage measures the amount of borrowing needed to achieve the reported performance. If leverage takes place, costs must be assigned to it. One way to measure leverage is as the ratio of **average dollar position size to average AUM**.\n",
        "\n",
        "  - **Maximum dollar position**: Maximum dollar position size informs us\n",
        "whether the strategy at times took dollar positions that greatly exceeded the average AUM. In general we will **prefer strategies that take maximum dollar positions close to the average AUM**, indicating that they do not rely on the occurrence of extreme events (possibly outliers).\n",
        "\n",
        "  - **Ratio of longs**: The ratio of longs show what proportion of the bets involved\n",
        "long positions. In long-short, market neutral strategies, ideally this value is close\n",
        "to **0.5**. **If not, the strategy may have a position bias**, or the backtested period may\n",
        "be too short and unrepresentative of future market conditions.\n",
        "\n",
        "  - **Frequency of bets**: The frequency of bets is the number of bets per year in\n",
        "the backtest. A sequence of positions on the same side is considered part of the\n",
        "same bet. A bet ends when the position is flattened or flipped to the opposite\n",
        "side. The number of bets is always smaller than the number of trades. A trade\n",
        "count would overestimate the number of independent opportunities discovered\n",
        "by the strategy.\n",
        "\n",
        "  - **Average holding period**: The average holding period is the average number of\n",
        "days a bet is held. High-frequency strategies may hold a position for a fraction\n",
        "of seconds, whereas low frequency strategies may hold a position for months\n",
        "or even years. Short holding periods may limit the capacity of the strategy. The\n",
        "holding period is related but different to the frequency of bets. For example,\n",
        "a strategy may place bets on a monthly basis, around the release of nonfarm\n",
        "payrolls data, where each bet is held for only a few minutes.\n",
        "\n",
        "  - **Annualized turnover**: Annualized turnover measures the ratio of the average\n",
        "dollar amount traded per year to the average annual AUM. High turnover may\n",
        "occur even with a low number of bets, as the strategy may require constant\n",
        "tuning of the position. High turnover may also occur with a low number of trades, if every trade involves flipping the position between maximum long and\n",
        "maximum short.\n",
        "\n",
        "  - **Correlation of underlying**: This is the correlation between strategy returns\n",
        "and the returns of the underlying investment universe. When the correlation is\n",
        "significantly positive or negative, the strategy is essentially holding or shortselling\n",
        "the investment universe, without adding much value.\n",
        "\n",
        "2. Performance - Dollar and returns numbers without risk adjustments\n",
        "  \n",
        "  - **PnL**: The total amount of dollars (or the equivalent in the currency of denomination) generated over the entirety of the backtest, including liquidation costs from the terminal position.\n",
        "  - **PnL from long positions**: The portion of the PnL dollars that was generated exclusively by long positions. This is an interesting value for assessing the bias of long-short, market neutral strategies.\n",
        "  - **Annualized rate of return**: The time-weighted average annual rate of total return, including dividends, coupons, costs, etc.\n",
        "  - **Hit ratio**: The fraction of bets that resulted in a positive PnL.\n",
        "  - **Average return from hits**: The average return from bets that generated a profit.\n",
        "  - **Average return from misses**: The average return from bets that generated a loss.\n",
        "\n",
        "3. Runs \n",
        "\n",
        "  Investment strategies rarely generate returns drawn from an IID process. In the absence of this property, strategy returns series exhibit frequent runs. Runs are uninterrupted sequences of returns of the same sign. Consequently, runs increase downside risk, which needs to be evaluated with proper metrics.\n",
        "  - \n",
        "\n",
        "\n",
        "4. Efficiency\n",
        "  - **Annualized Sharpe ratio**: This is the SR value, annualized by a factor\n",
        "$\\sqrt{a}$,\n",
        "where a is the average number of returns observed per year. This common annualization\n",
        "method relies on the assumption that returns are IID.\n",
        "  - **Information ratio**: This is the SR equivalent of a portfolio that measures its performance\n",
        "relative to a benchmark. It is the annualized ratio between the average\n",
        "excess return and the tracking error. The excess return is measured as the portfolio’s\n",
        "return in excess of the benchmark’s return. The tracking error is estimated\n",
        "as the standard deviation of the excess returns.\n",
        "  - **Probabilistic Sharpe ratio**: PSR corrects SR for inflationary effects caused\n",
        "by non-Normal returns or track record length. It should exceed 0.95, for the\n",
        "standard significance level of 5%. It can be computed on absolute or relative\n",
        "returns.\n",
        "  - **Deflated Sharpe ratio**: DSR corrects SR for inflationary effects caused by\n",
        "non-Normal returns, track record length, and multiple testing/selection bias.\n",
        "It should exceed 0.95, for the standard significance level of 5%. It can be computed\n",
        "on absolute or relative returns."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "r39ERfc8trP9",
        "colab_type": "text"
      },
      "source": [
        "#Exercise"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "QarDn1r-FlCq",
        "colab_type": "text"
      },
      "source": [
        "## 1 \n",
        "A strategy exhibits a high turnover, high leverage, and high number of bets, with\n",
        "a short holding period, low return on execution costs, and a high Sharpe ratio.\n",
        "Is it likely to have large capacity? What kind of strategy do you think it is?"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "4F1KzptJfvh_",
        "colab_type": "text"
      },
      "source": [
        "low capacity..\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Gra10h4oFohA",
        "colab_type": "text"
      },
      "source": [
        "##2.\n",
        "On the dollar bars dataset for E-mini S&P 500 futures, compute"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "RYXpVRWSf2ac",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 128
        },
        "outputId": "3c31cc8e-3bae-465a-d078-cc516c7faf58"
      },
      "source": [
        "from google.colab import drive\n",
        "drive.mount('/content/drive')"
      ],
      "execution_count": 2,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Go to this URL in a browser: https://accounts.google.com/o/oauth2/auth?client_id=947318989803-6bn6qk8qdgf4n4g3pfee6491hc0brc4i.apps.googleusercontent.com&redirect_uri=urn%3aietf%3awg%3aoauth%3a2.0%3aoob&response_type=code&scope=email%20https%3a%2f%2fwww.googleapis.com%2fauth%2fdocs.test%20https%3a%2f%2fwww.googleapis.com%2fauth%2fdrive%20https%3a%2f%2fwww.googleapis.com%2fauth%2fdrive.photos.readonly%20https%3a%2f%2fwww.googleapis.com%2fauth%2fpeopleapi.readonly\n",
            "\n",
            "Enter your authorization code:\n",
            "··········\n",
            "Mounted at /content/drive\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "h4tN0T_UgIMa",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "import numpy as np\n",
        "import pandas as pd"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "D4DYl5dEgOze",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 35
        },
        "outputId": "f33cf272-7056-43bd-f7dc-41ecf31eb28c"
      },
      "source": [
        "!pip install -q mlfinlab\n",
        "from mlfinlab import data_structures, features, filters, labeling, util"
      ],
      "execution_count": 4,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "\u001b[?25l\r\u001b[K     |██▊                             | 10kB 34.8MB/s eta 0:00:01\r\u001b[K     |█████▌                          | 20kB 3.0MB/s eta 0:00:01\r\u001b[K     |████████▎                       | 30kB 4.4MB/s eta 0:00:01\r\u001b[K     |███████████                     | 40kB 2.9MB/s eta 0:00:01\r\u001b[K     |█████████████▉                  | 51kB 3.6MB/s eta 0:00:01\r\u001b[K     |████████████████▋               | 61kB 4.2MB/s eta 0:00:01\r\u001b[K     |███████████████████▍            | 71kB 4.9MB/s eta 0:00:01\r\u001b[K     |██████████████████████▏         | 81kB 5.5MB/s eta 0:00:01\r\u001b[K     |█████████████████████████       | 92kB 6.1MB/s eta 0:00:01\r\u001b[K     |███████████████████████████▊    | 102kB 4.7MB/s eta 0:00:01\r\u001b[K     |██████████████████████████████▌ | 112kB 4.7MB/s eta 0:00:01\r\u001b[K     |████████████████████████████████| 122kB 4.7MB/s \n",
            "\u001b[?25h"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "z3NiPwojgRr2",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 90
        },
        "outputId": "4f64d112-2516-4fdf-beb0-88e195bff809"
      },
      "source": [
        "raw_dollar_bars = data_structures.get_dollar_bars('/content/drive/My Drive/Colab Notebooks/csv/clean_IVE_tickbidask2.csv', threshold=1000000)\n",
        "dollar_bars = raw_dollar_bars.set_index(pd.to_datetime(raw_dollar_bars.date_time))\n",
        "dollar_bars = dollar_bars.drop(columns='date_time')\n",
        "dollar_bars = dollar_bars.reset_index().drop_duplicates(subset='date_time', keep='last').set_index('date_time')"
      ],
      "execution_count": 5,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Reading data in batches:\n",
            "Batch number: 0\n",
            "Returning bars \n",
            "\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "yRNf4gmkf4-_",
        "colab_type": "text"
      },
      "source": [
        "###(a) HHI index on positive returns."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "sFbw9SxNhmxt",
        "colab_type": "text"
      },
      "source": [
        "the concentration of positive returns"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "kuSpBIFTgVXM",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "#————————————————————————————————————————\n",
        "def getHHI(betRet):\n",
        "  if betRet.shape[0]<=2:return np.nan\n",
        "  wght=betRet/betRet.sum()\n",
        "  hhi=(wght**2).sum()\n",
        "  hhi=(hhi-betRet.shape[0]**-1)/(1.-betRet.shape[0]**-1)\n",
        "  return hhi"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "NiMhmH4nhDiH",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 145
        },
        "outputId": "26ab89bb-7b22-4668-cbda-4ae7f66d2d17"
      },
      "source": [
        "ret = dollar_bars.close.pct_change().dropna()\n",
        "ret.head()"
      ],
      "execution_count": 7,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "date_time\n",
              "2009-09-28 09:53:49    0.001371\n",
              "2009-09-28 09:55:26    0.000000\n",
              "2009-09-28 10:02:52    0.002151\n",
              "2009-09-28 10:10:21    0.000780\n",
              "2009-09-28 10:19:36   -0.001170\n",
              "Name: close, dtype: float64"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 7
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "1qpzw0BEgxx_",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 35
        },
        "outputId": "cc8f14f5-63f4-462b-ac8a-a109e40c981e"
      },
      "source": [
        "rHHIPos = getHHI(ret[ret>=0]) # concentration of positive returns per bet\n",
        "rHHIPos"
      ],
      "execution_count": 8,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "0.00017091496355296337"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 8
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "YC9_Zns9hxBC",
        "colab_type": "text"
      },
      "source": [
        "### (b) HHI index on negative returns."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "WBwWNQRThc0E",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 35
        },
        "outputId": "7a07ce55-3d18-45ce-a960-b8cd1a232e23"
      },
      "source": [
        "rHHINeg = getHHI(ret[ret<0]) # concentration of negative returns per bet\n",
        "rHHINeg"
      ],
      "execution_count": 9,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "0.0001529867361240445"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 9
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "opY98YB9h51W",
        "colab_type": "text"
      },
      "source": [
        "###(c) HHI index on time between bars.\n"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "b_EZmHcHh-Pl",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 254
        },
        "outputId": "f483b98c-764b-4142-f572-f6fd6f9337c5"
      },
      "source": [
        "ret.groupby(pd.Grouper(freq='M')).count()"
      ],
      "execution_count": 10,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "date_time\n",
              "2009-09-30     52\n",
              "2009-10-31    320\n",
              "2009-11-30    246\n",
              "2009-12-31    245\n",
              "2010-01-31    207\n",
              "             ... \n",
              "2019-02-28    575\n",
              "2019-03-31    473\n",
              "2019-04-30    459\n",
              "2019-05-31    559\n",
              "2019-06-30    440\n",
              "Freq: M, Name: close, Length: 118, dtype: int64"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 10
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "GxoYoEgWhpVq",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 35
        },
        "outputId": "e04a0651-27ba-4bd4-9d53-a63b2d9dd840"
      },
      "source": [
        "tHHI = getHHI(ret.groupby(pd.Grouper(freq='M')).count()) # concentr. bets/month\n",
        "tHHI"
      ],
      "execution_count": 11,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "0.0032921257799305814"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 11
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "q52o-QiViV-U",
        "colab_type": "text"
      },
      "source": [
        "###(d) The 95-percentile DD.\n"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "6fQz87zcid5E",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "def computeDD_TuW(series,dollars=False):\n",
        "  # compute series of drawdowns and the time under water associated with them\n",
        "  df0=series.to_frame('pnl')\n",
        "  df0['hwm']=series.expanding().max()\n",
        "  df1=df0.groupby('hwm').min().reset_index()\n",
        "  df1.columns=['hwm','min']\n",
        "  df1.index=df0['hwm'].drop_duplicates(keep='first').index # time of hwm\n",
        "  df1=df1[df1['hwm']>df1['min']] # hwm followed by a drawdown\n",
        "  if dollars:dd=df1['hwm']-df1['min']\n",
        "  else:dd=1-df1['min']/df1['hwm']\n",
        "  tuw=((df1.index[1:]-df1.index[:-1])/np.timedelta64(1,'Y')).values# in years\n",
        "  tuw=pd.Series(tuw,index=df1.index[:-1])\n",
        "  return dd,tuw"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "dKY1F4LBi0vr",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "series = dollar_bars.close"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "iyaxNhEem0Iv",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "dd = computeDD_TuW(series)[0]"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "rxvuWfFKm7B6",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 35
        },
        "outputId": "b0475ff8-f5f3-4a17-9e41-7ddced344a43"
      },
      "source": [
        "np.percentile(dd,95)"
      ],
      "execution_count": 15,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "0.020718013511119477"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 15
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "5wi5eJn4ny04",
        "colab_type": "text"
      },
      "source": [
        "### (e) The 95-percentile TuW.\n"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "an9KuQS2nInf",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "tuw = computeDD_TuW(series)[1]"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "rijLmsNFn-qn",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 35
        },
        "outputId": "fcba51b7-d7d4-42ba-a00b-5a27581307c4"
      },
      "source": [
        "np.percentile(tuw,95)"
      ],
      "execution_count": 17,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "0.037676976851249655"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 17
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "TzQd1gyxoCAK",
        "colab_type": "text"
      },
      "source": [
        "###(f) Annualized average return.\n"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "0FXLJU7QoAkF",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "y = (series.index[-1] - series.index[0]).days/365"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "3d2KOXQ2ohsG",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "p= (1 + ret).prod()"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "VE-gt8e-on8j",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 35
        },
        "outputId": "a444ecd7-c435-4af2-9761-e93cb516d035"
      },
      "source": [
        "R = (p**(1/y))-1\n",
        "R"
      ],
      "execution_count": 20,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "0.088298960150196"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 20
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "VV38mchrqiOA",
        "colab_type": "text"
      },
      "source": [
        "### (g) Average returns from hits (positive returns)."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "nC9Sw3P-tGpz",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "pos_ret = ret[ret>0]"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "KoStshbFrEK9",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 35
        },
        "outputId": "5edae396-a4f7-426a-e7c8-bf838fd9aa44"
      },
      "source": [
        "(1+pos_ret).prod()**(1/len(pos_ret))-1"
      ],
      "execution_count": 22,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "0.0011348316679109516"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 22
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "sx7x6zpwvA0S",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 35
        },
        "outputId": "4ad58288-0fcf-4017-9d1d-9c894be613c9"
      },
      "source": [
        "pos_ret.mean()"
      ],
      "execution_count": 23,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "0.0011376924589268614"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 23
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "yTsCMpMmr55y",
        "colab_type": "text"
      },
      "source": [
        "###(h) Average return from misses (negative returns)."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "yPmXAj9ItT38",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "neg_ret = ret[ret<0]"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "Swv1fTfDtBId",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 35
        },
        "outputId": "7414c11d-d5b5-4c87-b37b-e623a1e601b8"
      },
      "source": [
        "(1+neg_ret).prod()**(1/len(neg_ret))-1"
      ],
      "execution_count": 25,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "-0.001137347181231152"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 25
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "B3khWSEavDif",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 35
        },
        "outputId": "c4c6724b-74b0-4354-92a9-82bcb4b053d8"
      },
      "source": [
        "neg_ret.mean()"
      ],
      "execution_count": 26,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "-0.0011342641708143742"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 26
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "NSPeC71TtatG",
        "colab_type": "text"
      },
      "source": [
        "### (i) Annualized SR."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "4KZv3OyWtkIu",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 35
        },
        "outputId": "1a42961d-5c67-4111-b441-bc343cd8152a"
      },
      "source": [
        "a = len(series)/y\n",
        "a"
      ],
      "execution_count": 27,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "6008.863764044944"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 27
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "kEieg4jjuw8V",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 35
        },
        "outputId": "d88135fb-8629-4fc5-d576-2abe5e2fcdb5"
      },
      "source": [
        "np.sqrt(a) * ret.mean() / ret.std()"
      ],
      "execution_count": 28,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "0.5142999702472026"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 28
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "5B_Aj_7cvV22",
        "colab_type": "text"
      },
      "source": [
        "###(j) Information ratio, where the benchmark is the risk-free rate."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "ME2M27ysuz3i",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 35
        },
        "outputId": "d40bb77e-a2c0-4556-e619-f9e16f1f942c"
      },
      "source": [
        "#let Rf=0.005%\n",
        "rf=0.005*0.01\n",
        "np.sqrt(a) * (ret.mean()-rf) / ret.std()"
      ],
      "execution_count": 33,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "-0.9466371550639973"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 33
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "do7G65pVNfGV",
        "colab_type": "text"
      },
      "source": [
        "### (k) PSR\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "r47Usix8QLYT",
        "colab_type": "text"
      },
      "source": [
        "$$ \\widehat{PSR}[SR^*] =  Z\\begin{bmatrix}\\frac{(\\widehat{SR}-SR^*) \\sqrt{T-1}}{\\sqrt{1-\\hat{\\gamma_3}\\widehat{SR}+\\frac{\\hat{\\gamma_4}-1}{4}\\widehat{SR}^2 }} \\end{bmatrix} $$"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "IZuhc5uLTrpf",
        "colab_type": "text"
      },
      "source": [
        "Bailey and L´opez de Prado [2012]"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "FZ0KjjFVT1mB",
        "colab_type": "text"
      },
      "source": [
        "Z [.] is the cumulative distribution function (CDF) of the standard Normal distribution,\n",
        "T is the number of observed returns, ̂𝛾3 is the skewness of the returns, and\n",
        "̂𝛾4 is the kurtosis of the returns (̂𝛾4 = 3 for Gaussian returns). For a given SR∗, ̂PSR\n",
        "increases with greater ̂SR (in the original sampling frequency, i.e. non-annualized), or\n",
        "longer track records (T), or positively skewed returns (̂𝛾3), but it decreases with fatter tails (̂𝛾4)."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "nTLRlh2OXb7Y",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "import scipy.stats as ss\n",
        "\n",
        "#https://github.com/esvhd/pypbo/blob/master/pypbo/pbo.py\n",
        "\n",
        "def psr(sharpe, T, skew, kurtosis, target_sharpe=0):\n",
        "    \"\"\"\n",
        "    Probabilistic Sharpe Ratio.\n",
        "    Parameters:\n",
        "        sharpe:\n",
        "            observed sharpe ratio, in same frequency as T.\n",
        "        T:\n",
        "            no. of observations, should match return / sharpe sampling period.\n",
        "        skew:\n",
        "            sharpe ratio skew\n",
        "        kurtosis:\n",
        "            sharpe ratio kurtosis\n",
        "        target_sharpe:\n",
        "            target sharpe ratio\n",
        "    Returns:\n",
        "        Cumulative probabilities for observed sharpe ratios under standard\n",
        "        Normal distribution.\n",
        "    \"\"\"\n",
        "    value = (\n",
        "        (sharpe - target_sharpe)\n",
        "        * np.sqrt(T - 1)\n",
        "        / np.sqrt(1.0 - skew * sharpe + sharpe ** 2 * (kurtosis - 1) / 4.0)\n",
        "    )\n",
        "    # print(value)\n",
        "    psr = ss.norm.cdf(value, 0, 1)\n",
        "    return psr"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "uZMbNAQHesIn",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "sharpe = ret.mean() / ret.std()"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "nMNEXpsriBYm",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 35
        },
        "outputId": "f35347fb-47c3-4e6b-c27a-e0ab7bfedd67"
      },
      "source": [
        "skew = ss.skew(ret)\n",
        "kurt = ss.kurtosis(ret)\n",
        "skew,kurt"
      ],
      "execution_count": 76,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "(10.04305600603968, 5203.254150903189)"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 76
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "gQhsc-XnXwvY",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 35
        },
        "outputId": "3c92dae4-7347-4012-ce5f-55662032df89"
      },
      "source": [
        "psr(sharpe, len(ret),skew,kurt)"
      ],
      "execution_count": 75,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "0.9467085634660752"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 75
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "SiiTyhz9MXlW",
        "colab_type": "text"
      },
      "source": [
        "### (l) DSR, where we assume there were 100 trials, and the variance of the trials' SR was 0.5."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "oBD47tCQXeOi",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "def expected_max(N):\n",
        "    \"\"\"\n",
        "    Expected maximum of IID random variance X_n ~ Z, n = 1,...,N,\n",
        "    where Z is the CDF of the standard Normal distribution,\n",
        "    E[MAX_n] = E[max{x_n}]. Computed for a large N.\n",
        "    \"\"\"\n",
        "    if N < 5:\n",
        "        raise AssertionError(\"Condition N >> 1 not satisfied.\")\n",
        "    return (1 - np.euler_gamma) * ss.norm.ppf(\n",
        "        1 - 1.0 / N\n",
        "    ) + np.euler_gamma * ss.norm.ppf(1 - np.exp(-1) / N)\n",
        "#---------------------------------------------------------------------------\n",
        "def dsr(test_sharpe, sharpe_std, N, T, skew, kurtosis):\n",
        "    \"\"\"\n",
        "    Deflated Sharpe Ratio statistic. DSR = PSR(SR_0).\n",
        "    See paper for definition of SR_0. http://ssrn.com/abstract=2460551\n",
        "    Parameters:\n",
        "        test_sharpe :\n",
        "            reported sharpe, to be tested.\n",
        "        sharpe_std :\n",
        "            standard deviation of sharpe ratios from N trials / configurations\n",
        "        N :\n",
        "            number of backtest configurations\n",
        "        T :\n",
        "            number of observations\n",
        "        skew :\n",
        "            skew of returns\n",
        "        kurtosis :\n",
        "            kurtosis of returns\n",
        "    Returns:\n",
        "        DSR statistic\n",
        "    \"\"\"\n",
        "    # sharpe_std = np.std(sharpe_n, ddof=1)\n",
        "    target_sharpe = sharpe_std * expected_max(N)\n",
        "\n",
        "    dsr_stat = psr(test_sharpe, T, skew, kurtosis, target_sharpe)\n",
        "\n",
        "    return dsr_stat"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "FP5O0yVKhdMN",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 35
        },
        "outputId": "dd766737-6d76-4df0-e705-8c1b33abe1d6"
      },
      "source": [
        "dsr(sharpe,np.sqrt(0.5),100,len(ret),skew,kurt)"
      ],
      "execution_count": 77,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "0.0"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 77
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "8Y0U9xFJTV_t",
        "colab_type": "text"
      },
      "source": [
        "Bailey and L´opez de Prado [2014]"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "7iU3f_X6U49Q",
        "colab_type": "text"
      },
      "source": [
        "## 3. Consider a strategy that is long one futures contract on even years, and is short one futures contract on odd years."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "ITEqfFpNU7id",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "bi = series.copy()\n",
        "bi[bi.index.year % 2 != 0] = 1\n",
        "bi[bi.index.year % 2 == 0] = -1"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "O7GBDtMqZza3",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "ret2 = ret*bi.dropna()"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "WI3HJ8j-af1R",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 35
        },
        "outputId": "3e6a2304-5fc2-49db-abd0-0584e1f8132c"
      },
      "source": [
        "rHHIPos2 = getHHI(ret2[ret2>=0])\n",
        "rHHINeg2 = getHHI(ret2[ret2<0])\n",
        "tHHI2 = getHHI(ret2.groupby(pd.Grouper(freq='M')).count())\n",
        "print(rHHIPos2, rHHINeg2, tHHI2)"
      ],
      "execution_count": 55,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "0.0001491558922275327 0.00017538563866829847 0.0032921257799305814\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "bTSgnsaTbq15",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 35
        },
        "outputId": "5843fadb-8b62-4e82-cc8f-02f88a01b8d8"
      },
      "source": [
        "p2= (1 + ret2).prod()\n",
        "AnnR = (p2**(-y))-1\n",
        "AnnR"
      ],
      "execution_count": 53,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "5.348213527901592"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 53
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "1pKDOZNub5uj",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 35
        },
        "outputId": "864ccc91-05af-4dfd-9157-4f5534aad24a"
      },
      "source": [
        "pos_ret2 = ret2[ret2>=0]\n",
        "neg_ret2 = ret2[ret2<0]\n",
        "print(\n",
        "pos_ret2.mean(),\n",
        "neg_ret2.mean())"
      ],
      "execution_count": 52,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "0.0010704985436283609 -0.001143628547932107\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "ja93UoK7cKSr",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 35
        },
        "outputId": "af2e32dd-7a5e-4057-b67f-f46810375e6e"
      },
      "source": [
        "np.sqrt(a) * ret2.mean() / ret2.std()\n",
        "#AnnSR"
      ],
      "execution_count": 56,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "0.012315168582883873"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 56
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "ESRp57R3cmTc",
        "colab_type": "text"
      },
      "source": [
        "## 4. The results from a 2-year backtest are that monthly returns have a mean of 3.6%, and a standard deviation of 0.079%."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "KMUhR3klcwj2",
        "colab_type": "text"
      },
      "source": [
        "### (a) What is the SR? (b) What is the annualized SR?"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "1qfKVHJpczo3",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 35
        },
        "outputId": "c587da11-fa8b-4a36-b249-edcf9475607c"
      },
      "source": [
        "a_4 = 12\n",
        "\n",
        "SR_4 = 3.6/0.079\n",
        "ASR_4= np.sqrt(a_4)*SR_4\n",
        "print(SR_4, ASR_4)"
      ],
      "execution_count": 58,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "45.56962025316456 157.85779512020147\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "VIpZIVrkdYVI",
        "colab_type": "text"
      },
      "source": [
        "##5. Following on exercise 1:\n",
        "(a) The returns have a skewness of 0 and a kurtosis of 3. What is the PSR?\n",
        "\n",
        "(b) The returns have a skewness of -2.448 and a kurtosis of 10.164. What is the\n",
        "PSR?"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "Jrnaxfjldt-W",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 35
        },
        "outputId": "f143eb44-1f9e-4f35-c2e8-08e19e3eb46a"
      },
      "source": [
        "psr(SR_4,24,0,3)"
      ],
      "execution_count": 64,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "0.9999999999939523"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 64
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "oQpBRNPyd2YC",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 35
        },
        "outputId": "95dc9e77-193d-4d96-9b3e-83acb57d58ab"
      },
      "source": [
        "psr(SR_4,24,-2.448,10.164)"
      ],
      "execution_count": 65,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "0.9991308782532012"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 65
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "T1b5H5gHgH9x",
        "colab_type": "text"
      },
      "source": [
        "## 6 What would be the PSR from 2.b, if the backtest had been for a length of 3 years?"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "QAXZgQOigMPR",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 35
        },
        "outputId": "c7f9820b-e035-43eb-c969-c213a65a42da"
      },
      "source": [
        "psr(SR_4,36,-2.448,10.164)"
      ],
      "execution_count": 66,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "0.9999440377053758"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 66
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "LdUX_SNpf1H8",
        "colab_type": "text"
      },
      "source": [
        "##7. A 5-year backtest has an annualized SR of 2.5, computed on daily returns. The skewness is -3 and the kurtosis is 10.\n",
        "(a) What is the PSR?\n",
        "\n",
        "(b) In order to find that best result, 100 trials were conducted. The variance of\n",
        "the Sharpe ratios on those trials is 0.5. What is the DSR?"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "uKYZLlLsfaRl",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "SR_7 = 2.5/np.sqrt(365)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "cu4auxiTgqC7",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 35
        },
        "outputId": "e145da54-7e9c-46fd-9081-5b7886ef675f"
      },
      "source": [
        "psr(SR_7, 5*365,-3,10)"
      ],
      "execution_count": 68,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "0.99999850616158"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 68
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "NgnpJaP_guyC",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 35
        },
        "outputId": "51ae9c7e-8e4e-4ad7-cf77-e70a67ee08fa"
      },
      "source": [
        "dsr(SR_7,np.sqrt(0.5),100,5*365,-3,10)"
      ],
      "execution_count": 72,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "0.0"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 72
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "9ikLgQYghCGi",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        ""
      ],
      "execution_count": 0,
      "outputs": []
    }
  ]
}